package com.module.aichat.ui.widget.inputview

import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity
import android.content.Context
import android.graphics.Rect
import android.os.Build
import android.util.DisplayMetrics
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewTreeObserver
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.LinearLayout
import com.common.base.utils.SpUtilsManagement


/**
 *
 * 作者：sosou
 *
 * 版本：1.0
 *
 * 创建日期：2025/06/25
 *
 * 描述：输入框防止键盘弹出跳动管理类
 *
 * 修订历史：
 *
 */
class EmotionKeyboard private constructor() {
    private var mActivity: Activity? = null
    private var mInputManager: InputMethodManager? = null//软键盘管理类
    var mEmotionLayout: View? = null//表情布局
    private var mEditText: EditText? = null
    private var mContentView: View? = null//内容布局view,即除了表情布局或者软键盘布局以外的布局，用于固定bar的高度，防止跳闪
    private var usableHeightPrevious = 0.0
    private var onGlobalLayoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null

    /**
     * 绑定内容view，此view用于固定bar的高度，防止跳闪
     *
     */
    fun bindToContent(contentView: View?): EmotionKeyboard {
        mContentView = contentView
        onGlobalLayoutListener =
            ViewTreeObserver.OnGlobalLayoutListener { possiblyResizeChildOfContent() }
        mContentView?.viewTreeObserver?.addOnGlobalLayoutListener(onGlobalLayoutListener)
        return this
    }

    fun removeListener() {
        mContentView?.viewTreeObserver?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
    }

    private fun possiblyResizeChildOfContent() {
        val r = Rect()
        mContentView?.rootView?.getWindowVisibleDisplayFrame(r)
        val usableHeightNow = r.bottom - r.top
        if (usableHeightNow.toDouble() != usableHeightPrevious) {
            val usableHeightSansKeyboard = mContentView?.rootView?.height ?: 0
            val heightDifference = usableHeightSansKeyboard - usableHeightNow
            if (heightDifference > usableHeightSansKeyboard / 4) {
                // 键盘弹出
            } else {
                // 键盘收起
                if (mEmotionLayout?.isShown != true && mListener != null) {
                    mListener?.hideKeyBoard()
                }
            }
            usableHeightPrevious = usableHeightNow.toDouble()
        }
    }

    /**
     * 绑定编辑框
     *
     */
    @SuppressLint("ClickableViewAccessibility")
    fun bindToEditText(editText: EditText?): EmotionKeyboard {
        mEditText = editText
        mEditText?.setOnTouchListener { v, event ->
            if (event.action == MotionEvent.ACTION_UP && mEmotionLayout?.isShown == true) {
                lockContentHeight() //显示软件盘时，锁定内容高度，防止跳闪。
                hideEmotionLayout(true) //隐藏表情布局，显示软件盘

                //软件盘显示后，释放内容高度
//                mEditText?.postDelayed({ unlockContentHeightDelayed() }, 100L)
                unlockContentHeightDelayed()
            }
            if (mListener != null) {
                mListener?.showKeyBoard()
            }
            false
        }
        return this
    }

    private var mListener: Listener? = null

    private var isFirst= true

    fun bindListener(listener: Listener?): EmotionKeyboard {
        mListener = listener
        return this
    }

    interface Listener {
        fun showKeyBoard()
        fun hideKeyBoard()
    }

    //显示键盘
    fun showKeyBoard() {
        if (mEmotionLayout?.isShown == true) {
//            lockContentHeight() //显示软件盘时，锁定内容高度，防止跳闪。
            hideEmotionLayout(true) //隐藏表情布局，显示软件盘
//            unlockContentHeightDelayed() //软件盘显示后，释放内容高度
        } else {
            showSoftInput()
        }
    }

    //显示emoji布局
    fun showEmojiView() {
        if (mEmotionLayout?.isShown == true) return
        if (isSoftInputShown()) {
            lockContentHeight() //锁定内容高度，防止跳闪。
            showEmotionLayout() //显示表情布局
            if (isFirst){//首次弹出不做延时
                isFirst = false
                unlockContentHeightDelayed(0) //解锁内容高度
            }else{
                unlockContentHeightDelayed(100) //解锁内容高度
            }
        } else {
            showEmotionLayout() //两者都没显示，直接显示表情布局
        }
    }

    /**
     * 设置表情内容布局
     *
     */
    fun bindEmotionView(emotionView: View?): EmotionKeyboard {
        mEmotionLayout = emotionView
        return this
    }

    fun build(): EmotionKeyboard {
        //设置软件盘的模式：SOFT_INPUT_ADJUST_RESIZE  这个属性表示Activity的主窗口总是会被调整大小，从而保证软键盘显示空间。
        //从而方便我们计算软件盘的高度
        mActivity?.window?.setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN or
                    WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
        )
        //隐藏软件盘
        hideSoftInput()
        return this
    }

    /**
     * 点击返回键时先隐藏表情布局
     */
    fun interceptBackPress(): Boolean {
        if (mEmotionLayout?.isShown == true) {
            hideEmotionLayout(false)
            return true
        }
        return false
    }

    fun showEmotionLayout() {
        var softInputHeight = getSupportSoftInputHeight()
        if (softInputHeight <= 0) {
            softInputHeight = keyBoardHeight
        }
        hideSoftInput()
        mEmotionLayout?.layoutParams?.height = softInputHeight
        mEmotionLayout?.visibility = View.VISIBLE
    }

    /**
     * 隐藏表情布局
     *
     * @param showSoftInput 是否显示软件盘
     */
    private fun hideEmotionLayout(showSoftInput: Boolean) {
        if (mEmotionLayout?.isShown == true) {
//            mEmotionLayout?.postDelayed({ mEmotionLayout?.visibility = View.GONE }, 200)
            mEmotionLayout?.visibility = View.GONE
            if (showSoftInput) {
                showSoftInput()
            }
        }
    }

    fun onlyHideEmotion() {
        if (mEmotionLayout?.isShown == true) {
            mEmotionLayout?.visibility = View.GONE
        }
    }

    /**
     * 锁定内容高度，防止跳闪
     */
    private fun lockContentHeight() {
        val params = mContentView?.layoutParams as LinearLayout.LayoutParams
        params.height = mContentView?.height ?: 0
        params.weight = 0.0f
    }

    /**
     * 释放被锁定的内容高度
     */
    private fun unlockContentHeightDelayed(delayedTime: Long = 0) {
        if (delayedTime <= 1) {
            (mContentView?.layoutParams as LinearLayout.LayoutParams).weight = 1.0f
            return
        }
        mEditText?.postDelayed({
            (mContentView?.layoutParams as LinearLayout.LayoutParams).weight = 1.0f
        }, delayedTime)
    }

    /**
     * 编辑框获取焦点，并显示软件盘
     */
    private fun showSoftInput() {
        mEditText?.requestFocus()
        mEditText?.post { mInputManager?.showSoftInput(mEditText, 0) }
    }

    /**
     * 隐藏软件盘
     */
    fun hideSoftInput() {
        mInputManager?.hideSoftInputFromWindow(mEditText?.windowToken, 0)
    }

    /**
     * 是否显示软件盘
     */
    private fun isSoftInputShown(): Boolean {
        return getSupportSoftInputHeight() != 0
    }

    /**
     * 获取软件盘的高度
     */
    private fun getSupportSoftInputHeight(): Int {
        val r = Rect()
        /**
         * decorView是window中的最顶层view，可以从window中通过getDecorView获取到decorView。
         * 通过decorView获取到程序显示的区域，包括标题栏，但不包括状态栏。
         */
        mActivity?.window?.decorView?.getWindowVisibleDisplayFrame(r)
        //获取屏幕的高度
        val screenHeight = mActivity?.window?.decorView?.rootView?.height ?: 0
        //计算软件盘的高度
        var softInputHeight = screenHeight - r.bottom
        /**
         * 某些Android版本下，没有显示软键盘时减出来的高度总是144，而不是零，
         * 这是因为高度是包括了虚拟按键栏的(例如华为系列)，所以在API Level高于20时，
         * 我们需要减去底部虚拟按键栏的高度（如果有的话）
         */
        if (Build.VERSION.SDK_INT >= 20) {
            // When SDK Level >= 20 (Android L), the softInputHeight will contain the height of softButtonsBar (if has)
            softInputHeight -= getSoftButtonsBarHeight()
        }
        if (softInputHeight < 0) {
            Log.w(TAG, "EmotionKeyboard--Warning: value of softInputHeight is below zero!")
        }
        //存一份到本地
        if (softInputHeight > 0) {
            SpUtilsManagement.putInt(SHARE_PREFERENCE_SOFT_INPUT_HEIGHT, softInputHeight)
        }
        return softInputHeight
    }

    /**
     * 底部虚拟按键栏的高度
     *
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    private fun getSoftButtonsBarHeight(): Int {
        val metrics = DisplayMetrics()
        //这个方法获取可能不是真实屏幕的高度
        mActivity?.windowManager?.defaultDisplay?.getMetrics(metrics)
        val usableHeight = metrics.heightPixels
        //获取当前屏幕的真实高度
        mActivity?.windowManager?.defaultDisplay?.getRealMetrics(metrics)
        val realHeight = metrics.heightPixels
        return if (realHeight > usableHeight) {
            realHeight - usableHeight
        } else {
            0
        }
    }

    companion object {
        private const val SHARE_PREFERENCE_SOFT_INPUT_HEIGHT = "soft_input_height"
        private const val TAG = "EmotionKeyboard"

        /**
         * 外部静态调用
         *
         */
        fun with(activity: Activity): EmotionKeyboard {
            val emotionInputDetector = EmotionKeyboard()
            emotionInputDetector.mActivity = activity
            emotionInputDetector.mInputManager =
                activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            return emotionInputDetector
        }

        /**
         * 获取软键盘高度，由于第一次直接弹出表情时会出现小问题，787是一个均值，作为临时解决方案
         */
        val keyBoardHeight: Int
            get() =  SpUtilsManagement.getInt(SHARE_PREFERENCE_SOFT_INPUT_HEIGHT, 787)
    }
}